﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using TestXNA3.Render;

namespace TestXNA3.Resources.Shaders
{
    public class StaticMeshDefaultShader : ShaderResource
    {
        static protected Effect _staticMeshDefaultShader = null;

        // Diffuse texture
        private TextureResource _diffuse = new TextureResource("default");
        public TextureResource Diffuse
        {
            get { return _diffuse; }
            set { _diffuse = value; }
        }

        // Normal texture
        private TextureResource _normal = new TextureResource("default_normal");
        public TextureResource Normal
        {
            get { return _normal; }
            set { _normal = value; }
        }

        // Draw as unlit
        private bool _unlit = false;
        public bool Unlit
        {
            get { return _unlit; }
            set { _unlit = value; }
        }

        // Set parallax height
        private float _height = 0.06f;
        public float Height
        {
            get { return _height; }
            set { _height = value; }
        }

        public StaticMeshDefaultShader()
        {
            if (_staticMeshDefaultShader == null)
            {
                _staticMeshDefaultShader = GameStartup.ContentManager.Load<Effect>("Shaders/StaticMeshDefaultShader");
            }
            Effect = _staticMeshDefaultShader;
            foreach(EffectTechnique t in Effect.Techniques)
            {
                if (t.Name == "Default")
                {
                    _defaultTechnique = t;
                }else
                if (t.Name == "DepthOnly")
                {
                    _depthOnlyTechnique = t;
                }
            }
        }

        // Allow to change techniques
        protected EffectTechnique _depthOnlyTechnique = null;
        public override void SetTechnique(SceneRenderer.EDrawMode drawMode)
        {
            if (drawMode == SceneRenderer.EDrawMode.Default)
            {
                Effect.CurrentTechnique = _defaultTechnique;
            }else
            if (drawMode == SceneRenderer.EDrawMode.DepthOnly)
            {
                Effect.CurrentTechnique = _depthOnlyTechnique;
            }
        }

        // Apply shader specific params
        public override void ApplyShaderConst()
        {
            Effect.Parameters["World"].SetValue(_world);
            Effect.Parameters["View"].SetValue(_view);
            Effect.Parameters["Projection"].SetValue(_projection);
            
            Matrix worldViewProj = _world * _view * _projection;
            Effect.Parameters["WorldViewProjection"].SetValue(worldViewProj);

            Effect.Parameters["EyePosition"].SetValue(_eyePosition);
            Effect.Parameters["DiffuseTexture"].SetValue(_diffuse.Texture);
            Effect.Parameters["NormalTexture"].SetValue(_normal.Texture);

            Effect.Parameters["Unlit"].SetValue(Unlit);
            Effect.Parameters["g_DepthScale"].SetValue(Height);
        }

        public override void Save(System.IO.BinaryWriter writer)
        {
            writer.Write(Diffuse.TextureName);
            writer.Write(Normal.TextureName);
            writer.Write(Unlit);
            writer.Write(Height);
        }

        public override void Load(System.IO.BinaryReader reader)
        {
            Diffuse.TextureName = reader.ReadString();
            Normal.TextureName = reader.ReadString();
            Unlit = reader.ReadBoolean();
            Height = reader.ReadSingle();
        }

        public override void DuplicateProperties(ShaderResource to)
        {
            if (to.GetType() != GetType())
                return;

            StaticMeshDefaultShader to2 = to as StaticMeshDefaultShader;
            to2.Diffuse.TextureName = Diffuse.TextureName;
            to2.Normal.TextureName = Normal.TextureName;
            to2.Unlit = Unlit;
            to2.Height = Height;
        }
    }
}
